from machine import I2S  # 导入I2S协议库，什么是I2S自行百度
from machine import Pin
 
 
""" 
GPIO13 -- DIN sd_pin
GPIO12 --- BCLK sck_pin
GPIO14 -- LRC ws_pin
GND -- GND
5V或3.3V -- VCC
"""
 
# 初始化引脚定义
sck_pin = Pin(12) # 串行时钟输出
ws_pin  = Pin(14)  # 字时钟
sd_pin  = Pin(13)  # 串行数据输出

 
"""
sck 是串行时钟线的引脚对象
ws 是单词选择行的引脚对象
sd 是串行数据线的引脚对象
mode 指定接收或发送
bits 指定样本大小（位），16 或 32
format 指定通道格式，STEREO（左右声道） 或 MONO(单声道)
rate 指定音频采样率（样本/秒）
ibuf 指定内部缓冲区长度（字节）
"""
 
# 初始化i2s
audio_out = I2S(1,
                sck=sck_pin,
                ws=ws_pin,
                sd=sd_pin,
                mode=I2S.TX,
                bits=16,
                format=I2S.MONO,
                rate=16000,
                ibuf=20000)
 
 

def playwav(wavtempfile):
    with open(wavtempfile,'rb') as f:
     
        # 跳过文件的开头的44个字节，直到数据段的第1个字节
        pos = f.seek(44) 
        # 用于减少while循环中堆分配的内存视图
        wav_samples = bytearray(1024)
        wav_samples_mv = memoryview(wav_samples)
        print("开始播放音频...")
        
        #并将其写入I2S DAC
        while True:
            try:
                num_read = f.readinto(wav_samples_mv)
                
                # WAV文件结束
                if num_read == 0: 
                    break
     
                # 直到所有样本都写入I2S外围设备
                num_written = 0
                while num_written < num_read:
                    num_written += audio_out.write(wav_samples_mv[num_written:num_read])
                    
            except Exception as ret:
                print("产生异常...", ret)
                break
wavtempfile = "audio.wav"
playwav(wavtempfile)